package com.daffodil.framework.aspectj;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.daffodil.core.annotation.Dict;
import com.daffodil.core.entity.TableInfo;
import com.daffodil.framework.shiro.service.DictionaryService;
import com.daffodil.system.entity.SysDictionary;
import com.daffodil.util.StringUtils;

/**
 * 解决table表字典数据转换
 * @author yweijian
 * @date 2021年4月1日
 * @version 1.0
 * @description
 */
@Aspect
@Component
public class TableInfoAspect {
	
	private static final Logger log = LoggerFactory.getLogger(TableInfoAspect.class);
	
	@Autowired
	protected DictionaryService dictionaryService;

	// 配置织入点
	@Pointcut("@annotation(org.springframework.web.bind.annotation.ResponseBody)")
	public void tableinfoPointCut() {
		
	}
	
	@AfterReturning(pointcut = "tableinfoPointCut()", returning = "results")
	public Object doAfter(JoinPoint joinPoint, Object results) {
		if(results instanceof TableInfo) {
			TableInfo tableInfo = (TableInfo) results;
			return this.handleTableInfo(joinPoint, tableInfo );
		}
		return results;
	}
	
	protected TableInfo handleTableInfo(final JoinPoint joinPoint, TableInfo tableInfo) {
		List<?> list = tableInfo.getData();
		if(list != null && list.size() > 0) {
			tableInfo.setRows(this.getDictRows(list));
		}
		return tableInfo;
	}
	
	/**
	 * 处理存在字典注解的字段，并回显中文字典含义<br>
	 * 获取字典回显值的数据列表
	 * @param list 原始数据
	 * @return
	 */
	private List<?> getDictRows(List<?> list){
		if(StringUtils.isNotEmpty(list)){
			Map<String, List<SysDictionary>> map = this.getDictionaryList(list.get(0));
			this.setDictRows(map, list);
		}
		return list;
	}
	
	/**
	 * 获取字段对应的字典值
	 * @param entity
	 * @return
	 */
	private Map<String, List<SysDictionary>> getDictionaryList(Object entity){
		Map<String, List<SysDictionary>> map = null;
		if(entity != null){
			Field[] fields = entity.getClass().getDeclaredFields();
			if(StringUtils.isNotEmpty(fields)){
				map = new HashMap<String, List<SysDictionary>>();
				for(Field field : fields){
					Dict annotation = getDictAnnotation(field, entity);
					if(StringUtils.isNotNull(annotation)){
						String dictLabel = annotation.value();
						List<SysDictionary> dicts = dictionaryService.getDict(dictLabel);
						map.put(field.getName(), dicts);
					}
				}
			}
		}
		return map;
	}
	
	/**
	 * 获取字典注解
	 * @param field
	 * @param entity
	 * @return
	 */
	private Dict getDictAnnotation(Field field, Object entity) {
		Dict annotation = field.getAnnotation(Dict.class);
		if(StringUtils.isNull(annotation)){
			try {
				Method get = entity.getClass().getMethod("get" + StringUtils.capitalize(field.getName()));
				annotation = StringUtils.isNotNull(get) ? get.getAnnotation(Dict.class) : null;
			} catch (NoSuchMethodException | SecurityException e) {
			}
		}
		return annotation;
	}
	
	/**
	 * 将数据列表转成对应的字典值的回显值
	 * @param map 获取字段对应的字典值
	 * @param list 原始数据
	 */
	private void setDictRows(Map<String, List<SysDictionary>> map, List<?> list){
		if(StringUtils.isNotEmpty(map)){
			for(int i = 0; i < list.size(); i++){
				Object entity = list.get(i);
				for (Map.Entry<String, List<SysDictionary>> entry : map.entrySet()) { 
					try {
						List<SysDictionary> dicts = entry.getValue();
						Method get = entity.getClass().getMethod("get" + StringUtils.capitalize(entry.getKey()));
						Method set = entity.getClass().getMethod("set" + StringUtils.capitalize(entry.getKey()), String.class);
						Object value = get.invoke(entity);
						if(StringUtils.isNotEmpty(dicts)){
							for(SysDictionary dict : dicts){
								if(value != null && value.equals(dict.getDictValue())){
									set.invoke(entity, dict.getDictName());
									break;
								}
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
						log.warn(e.getMessage());
					}
				}
			}
		}
	}
}
